/*Tetris v0.0*/

/*glossary

-pos= position

*/

#include <stdio.h>
#include <grx20.h>
#include <math.h>/*for absolute value*/
#include <conio.h> /*for random*/
#include <grxkeys.h>
#include <windows.h>

/*
#define GrKey_Up                   0x0148
#define GrKey_Left                 0x014b
#define GrKey_Right                0x014d
#define GrKey_Down                 0x0150
#define GrKey_x                    0x0078
#define GrKey_z                    0x007a
*/
#define DEBUG 1

#define PIECESIZE 4
#define MAX_MENU_ITEMS 10
#define CHARW 8
#define CHARH 12

#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3

#define GRIDX 8
#define GRIDY 16
#define PIECESIZE 4
#define TILESIZE 25
#define XRES GrScreenX()
#define YRES GrScreenY()

/* STRUCTURES */
struct sPiece
    {
    int pieceNo;
    int coordX;
    int coordY;
    int rotation; /*0-3*/
    int shape[PIECESIZE][PIECESIZE];
    int status; /*off, current, stop*/
    int color;
    int type; 
    };

struct sGame
{
int grid[GRIDX][GRIDY];
int currentPiece;

int contextpointer;
};


struct menuItem
    {
    char text[25];
    int xPos;
    int yPos;
    };

/*FUNCTION PROTOTYPES*/
int makeShape(int shapeData, int find);
int mainMenu(int *quitFlag);
int onePlayerGame();
void howToPlay();
void tbPause();
void tbErrorMsg( char msg[] );



/*MAIN FUNCTION*/
int main(void)
    {
    int quitFlag = 0;
    int menuPos = 0;

    /*FreeConsole();*/ /*deletes command prompt*/
    GrSetMode( GR_width_height_color_graphics, 640, 480, 32768 );
    GrSetRGBcolorMode();
    while(quitFlag == 0)
        {
        switch (menuPos)
            {
            case 0:
                {
                menuPos = mainMenu(&quitFlag);
                break;
                }
            case 1:
                {
                menuPos = onePlayerGame();
                break;
                }
            }
        }
    return 0;
    }


/*functions:*/

/*goes into one player game mode*/
int onePlayerGame()
    {
    int i=0,j=0,k=0;
    int GridStartX= 50;
    int GridStartY= YRES-50;
    int resetFlag=0, menuFlag=0;
    struct sGame game;
    
    game.currentPiece=0;
    
    tbErrorMsg("in GAME");
    GrClearScreen(0);
    
    /*set grid to 0*/
    for (i=0; i<GRIDX; i++)
        {
        for (j=0; j<GRIDY; j++)
            {
            game.grid[i][j] = 0;
            }
        }
    
   /* while(resetFlag==0 && menuFlag==0)
        {
          }*/
        /*check button press*/
        /*react to button press iff neccesary
        by:
            -turning shape
                -load into shape turn func.
                -check for conflict
                -else ignore
                -update if neccesary
            -speeding up play
                -if button pressed, speed changed
                -if not pressed, speed normal
            -moving shape:
                -current shape x cord +/-1
                -check for conflict
                -update
            -accessing option
                -restart
                -back to menu
                -change colour(prefferences)
                -    
        */
        
        /*
        Increment time:
            -check if time second has changed
            -ifso reprint clock
            -update moving block position (using block speed)
        */
        
        /*
        when shapes have been moved, check for overlapping
        then act accordingly
        */
        /**/
        /**/
        /**/
        /*update graphics
            -make function?
            -check what contexts have changed
            -update relavant contexts
            -compile contexts
            -print to screen*/
    
    game.grid[3][3]=1;
    game.grid[3][4]=1;
    game.grid[4][4]=1;
    game.grid[5][4]=1;
    
    
    
    /*print current grid*/
    for (i=0; i< GRIDX; i++)
        {
        for (j=0; j<GRIDY; j++)
            {
            if(game.grid[i][j] == 0)
                {
                GrFilledBox(
                    GridStartX+TILESIZE*i,
                    GridStartY-TILESIZE*j,
                    GridStartX+TILESIZE*(i+1),
                    GridStartY-TILESIZE*(j+1),
                    GrWhite() );
                }
            }
        }
    
    tbPause();
    GrKeyRead();
    return 0;
    }


int makeShape(int shapeData, int find)
    {
    int a;
    }
    
    
/* mainMenu function */
int mainMenu(int *quitFlag)
    {
    int listStartX = 100, listStartY = 100, listGapSize = 20;
    int noListItems = 0, listPos = 0, lastListPos = 0, quitPos=0, howToPlayPos=0;
    int lastKey = 0;
    int a = 0;
    int needMenuPrint=1;
    struct menuItem mainList[MAX_MENU_ITEMS];
    
    tbErrorMsg("in MAIN");
    
    /*saves menu text and no. of list items*/
    sprintf(mainList[a++].text, " Start 1 player game ");
    sprintf(mainList[a++].text, " Start 2 player game ");
    howToPlayPos=a;
    sprintf(mainList[a++].text, " How to play");
    sprintf(mainList[a++].text, " Options ");
    sprintf(mainList[a++].text, " View Highscores ");
    quitPos=a;
    sprintf(mainList[a++].text, " Exit Game ");
    noListItems=a;
    
    /*set positions of menu items*/
    for (a = 0; a < noListItems ; a++)
        {
        mainList[a].xPos = listStartX;
        mainList[a].yPos = listStartY + a *listGapSize;
        }
    
    /*Menu Loop*/
    while(1)
        {
        if (needMenuPrint == 1)
        {
        GrClearScreen(0);
        /*print menu items*/
        GrTextXY (listStartX, listStartY - 2*listGapSize,
                  "TETRIS v0.0", GrWhite(), GrBlack() );
        
        /*print*/
        for (a = 0; a < noListItems ; a++)
        {
        GrTextXY (
            mainList[a].xPos, mainList[a].yPos,
            mainList[a].text,
            GrWhite(), GrBlack());
        }
        
        /*highlight line*/
        GrTextXY (
            mainList[listPos].xPos, mainList[listPos].yPos,
            mainList[listPos].text,
            GrBlack(), GrWhite());
        
        needMenuPrint=0;
        }
        
        /*waits for keypress*/
        tbPause();
        
        lastKey = GrKeyRead();
        
        /*for each keypress*/
        switch(lastKey)
            {
            case GrKey_Up:
                {
                listPos--;
                if (listPos < 0)
                 {listPos = noListItems-1;}
                break;
                }
            
            case GrKey_Down:
                {
                listPos++;
                if (listPos > (noListItems-1) )
                    {listPos=0;}
                break;
                }
            
            case GrKey_z:
                {
                if (listPos == 0)
                    {
                    return 1;
                    }
                if (listPos == quitPos)
                    {
                    *quitFlag=1;
                    return 0;
                    }
                if (listPos == howToPlayPos)
                    {
                    howToPlay();
                    }

                break;
                }
            }/*end of switch*/
        
        if (listPos != lastListPos)
        {
        needMenuPrint=1;
        lastListPos=listPos;
        }
        }/*end of menu while*/
    }/*end of mainmenu function*/

void howToPlay()
    {
    int dimX, dimY, startX, startY;
    int lines=0;
    char text[10][50]={0};
    int i;
    
    tbErrorMsg("in HOW TO PLAY");
    
    dimX=XRES/2;
    dimY=YRES/2;
    startX=XRES/4;
    startY=YRES/4;
    
    /*menu text*/
    sprintf(&text[lines++][0],"         How to play");
    lines++;
    sprintf(&text[lines++][0],"Left and Right keys move the block");
    sprintf(&text[lines++][0],"Up Rotates the block");
    sprintf(&text[lines++][0],"Down speeds up the block");
    sprintf(&text[lines++][0],"'Z' is select");
    sprintf(&text[lines++][0],"'X' is back");
    lines++;
    sprintf(&text[lines++][0],"press any key to return");
    
    /*create context*/
    GrContext *instructContext;
    instructContext = GrCreateContext (dimX,dimY,NULL,NULL);
    
    /*void GrBitBlt(GrContext *dest,int x,int y,GrContext *source,
              int x1,int y1,int x2,int y2,GrColor op);
    x, y is the position in the destination context, and x1, y1, x2, y2 the area from the source context to be transfered.           
    */
    
    /*paste 0 screen into context*/
    GrBitBlt(instructContext,0,0,
             0, startX, startY, startX+dimX, startY+dimY, GrWRITE);
             
    /*draw box and text to main screen*/
    GrFilledBox(startX, startY, startX+dimX-1, startY+dimY-1, GrAllocColor(150,150,255));
    for (i=0; i<lines; i++)
        {
        GrTextXY(startX+20,startY+(dimY-lines*CHARH)/2+CHARH*i,text[i],GrBlack(),GrNOCOLOR);
        }
    
    /*pause*/
    tbPause();
    GrKeyRead();
    
    /*reprint old buffer*/
    GrBitBlt(0,startX,startY,
             instructContext, 0, 0, dimX, dimY, GrWRITE);
                       
    /*destroy context*/
    GrDestroyContext(instructContext);
    }

void tbPause()
    {
    while( !GrKeyPressed() )
        {}
    }

void tbErrorMsg( char msg[] )
    {
    if (DEBUG == 1)
        {
        printf("%s\n",msg);
        }
    }
